package com.lobov.run.yale;

import java.io.FileWriter;
import java.io.IOException;

import com.lobov.entities.ContainerOfSnipsYale;
import com.lobov.entities.Timer;
import com.lobov.entities.yale.MatrixYale;
import com.lobov.entities.yale.SnipYale;
import com.lobov.operations.yale.MultiplicationYale;
import com.lobov.utils.Compressor;
import com.lobov.utils.Generator;
import com.lobov.utils.Transformer;
import com.lobov.utils.yale.CutterYale;

public class RunYale {

	public static void main(String[] args) throws Exception {

		log("Старт! \n");
		// firstTest();
		// for (int i = 0; i < 2; i++) {
		// for (int d = 2; d <= 10; d+=2) {
		// double density = d*0.1;
		// write_to_file("плотность  " + density);
		// multipleGeneratedMatrixes(1000, 1000, density);
		// }
		// }
		// firstTransposeTest();
		// compressTest();
		// multipleGeneratedMatrixes(1000, 1000, 0.2);
//		multipleGeneratedCompressedMatrixes(1000, 1000, 0.1d, 0.1d);
//		cuttingMatrix();
//		mainMainTest();
		print50();
	}
	
	@SuppressWarnings("unused")
	private static void multipleGeneratedMatrixes(int xLength, int yLength,
			double density) throws Exception {
		Timer timer = new Timer();
		timer.startTimer();
		MatrixYale m1 = Generator.generateUnCompressedHorisontalMatrixYale(
				xLength, yLength, density);

		MatrixYale m2 = Generator.generateUnCompressedHorisontalMatrixYale(
				xLength, yLength, density);

		MatrixYale m3 = MultiplicationYale.newInstance().matrixOnMatrix(m1, m2,
				false);
		log("Перемножение полных матриц " + xLength + " на "
				+ yLength + " закончено \n");
		// write_to_file("Произведение матриц 1 и 2: \n" + m3 + "\n");
		// write_to_file(m3);
		log("ВРЕМЯ ПРОГОНА: " + timer.getTime() + " мс.");
		m1 = Compressor.compressMatrixYale(m1);
		m2 = Compressor.compressMatrixYale(m2);
		timer = new Timer();
		timer.startTimer();
		m3 = MultiplicationYale.newInstance().matrixOnMatrix(m1, m2, false);
		log("Перемножение сжатых матриц " + xLength + " на "
				+ yLength + " закончено \n");
		log("ВРЕМЯ ПРОГОНА: " + timer.getTime() + " мс.");
	}

	private static void multipleGeneratedCompressedMatrixes(int xLength,
			int yLength, double startDensity, double h) throws Exception {
		log("Перемножаем квадратные матрицы размерностью "
				+ xLength + "x" + yLength + ": \n");
		for (double density = startDensity; density <= 1; density += h) {
			MatrixYale m1 = Generator.generateUnCompressedHorisontalMatrixYale(
					xLength, yLength, density);
			MatrixYale m2 = Generator.generateUnCompressedHorisontalMatrixYale(
					xLength, yLength, density);
			m1 = Compressor.compressMatrixYale(m1);
			m2 = Compressor.compressMatrixYale(m2);
			MatrixYale m3 = MultiplicationYale.newInstance().matrixOnMatrix(m1,
					m2, false);
			Timer timer = new Timer();
			timer.startTimer();
			m3 = MultiplicationYale.newInstance().matrixOnMatrix(m1, m2, false);
			log("разреженность -  " + Math.round(density * 100) + "% ");
			log("   время умножения: " + timer.getTime()
					+ " мс. \n");
		}
	}
	
	@SuppressWarnings("unused")
	private static void firstTest() throws Exception {
		MatrixYale m1 = getTest1Matrix();
		log("Матрица 1: \n" + m1 + "\n");
		MatrixYale m2 = getTest2Matrix();
		log("Матрица 2: \n" + m2 + "\n");

		MatrixYale m3 = MultiplicationYale.newInstance().matrixOnMatrix(m1, m2,
				false);
		log("Произведение матриц 1 и 2: \n" + m3 + "\n");
		log("Перемножение закончено");
		log(m3.toString());
	}
	@SuppressWarnings("unused")
	private static void firstTransposeTest() throws Exception {
		MatrixYale matrix = getTest1Matrix();
		log("Матрица : \n" + matrix + "\n");
		MatrixYale matrix2 = Transformer.transposeMatrixYale(matrix);
		log("После транспонирования: \n" + matrix2 + "\n");
	}

	private static MatrixYale getTest1Matrix() throws Exception {
		MatrixYale m1 = new MatrixYale(3, 3);
		m1.setElementByXY(1, 1, -3);
		m1.setElementByXY(2, 1, 3);
		m1.setElementByXY(3, 1, 1);
		m1.setElementByXY(1, 2, 2);
		m1.setElementByXY(2, 2, -1);
		m1.setElementByXY(3, 2, 5);
		m1.setElementByXY(1, 3, 1);
		m1.setElementByXY(2, 3, 2);
		m1.setElementByXY(3, 3, 4);
		return m1;
	}

	private static MatrixYale getTest2Matrix() throws Exception {
		MatrixYale m2 = new MatrixYale(2, 3);
		m2.setElementByXY(1, 1, 2);
		m2.setElementByXY(2, 1, -2);
		m2.setElementByXY(1, 2, 1);
		m2.setElementByXY(2, 2, 3);
		m2.setElementByXY(1, 3, 2);
		m2.setElementByXY(2, 3, 3);
		return m2;
	}
	@SuppressWarnings("unused")
	private static void compressTest() throws Exception {
		MatrixYale matrix = Generator.generateUnCompressedHorisontalMatrixYale(
				10, 10, 0.2);
		log("Матрица : \n" + matrix + "\n");
		MatrixYale matrix2 = Compressor.compressMatrixYale(matrix);
		log("После сжатия: \n" + matrix2 + "\n");
	}
	
	//проверка правильно ли режется матрица и умножается на другую матрицу
	@SuppressWarnings("unused")
	private static void cuttingMatrix() throws Exception{
		MatrixYale matrix1 = Generator.generateUnCompressedHorisontalMatrixYale(
				10, 10, 0.3);
		MatrixYale matrix2 = Generator.generateUnCompressedHorisontalMatrixYale(
				10, 10, 0.3);
		MatrixYale matrixYale_mult_matrixes = MultiplicationYale.newInstance().matrixOnMatrix(matrix1, matrix2, false);
		log(matrix1.toString());
		log("--------------------------------");
		//режем матрицу на лоскуты и кладем их в контейнер
		ContainerOfSnipsYale container =  CutterYale.cutMatrixHorizontal(matrix1, 3);
		// 
		SnipYale[] snips = container.getSnips();
		//
		SnipYale[] snips_new = new  SnipYale[snips.length];
		//		
		for(int i=0; i<snips.length; i++){
			log(snips[i].toString());
			snips_new[i] = MultiplicationYale.newInstance().snipOnMatrix(snips[i], matrix2, false);
		}
		ContainerOfSnipsYale cont_new = new ContainerOfSnipsYale(container.getSnips().length, container.getSnipsXLength());
		cont_new.setSnips(snips_new);
		log("С разрезанием матрицы:");
		MatrixYale matrixYale_cut_mult = cont_new.toMatrix();
		log(matrixYale_mult_matrixes.toString());
		log("При простом перемножение матриц");
		log(matrixYale_cut_mult.toString());
	}
	
	private static void mainMainTest() throws Exception {
		mainTest(false);
		mainTest(true);
	}
	
	//перемножение матриц йельского формата в цикле с переменной размерностью
	private static void mainTest(boolean compress) throws Exception {
		int h = 1000; //размер матриц
		int val = 1000;
		int endValue = 6000;
//		boolean compress = false;
		double density = 0.2; 
		log("Single core "+ (compress?"cжатый формат":"полный формат "));
		while (val <= endValue) {
			// генерируем матрицу 1
			MatrixYale matrix1 = Generator.generateUnCompressedHorisontalMatrixYale(val,
					val, density);
			// генерируем матрицу 2
			MatrixYale matrix2 = Generator.generateUnCompressedHorisontalMatrixYale(val,
					val, density);
			if(compress){
				matrix1 = Compressor.compressMatrixYale(matrix1);
				matrix2 = Compressor.compressMatrixYale(matrix2);
			}
			Timer timer = new Timer();
			timer.startTimer();
			MatrixYale mult_matrix = MultiplicationYale.newInstance().matrixOnMatrix(matrix1, matrix2 , false);
			long time = timer.getTime();
			
			log(val + "X" + val + " - " + time + " мс. -" + (compress?"cжатый":"полный формат ")
					+ " c " + density*100 +"%-ной наполненностью матриц");
			val+=h;
		}
	}
	
	private static void log(String str) throws IOException, InterruptedException  {
			FileWriter writer = new FileWriter("/home/sanix/reportNEW1core.txt", true);
			writer.write(str + "\n");
			System.out.println(str);
			writer.close();
	}
	
	
	private static void print50(){
		MatrixYale matrix1 = Generator.generateUnCompressedHorisontalMatrixYale(50,
				50, 0.2);
		System.out.println(matrix1);
	}
	
	

}
